import { FormEvent, useRef, useState } from "react";
import { FormContext } from "./formContext";

interface FormProps extends React.HTMLAttributes<HTMLFormElement> {
  children?: React.ReactNode;
  onValueChange?: (key: string, value: any) => void;
  initialValues?: Record<string, any>;
  onFinish?: (values: Record<string, any>) => void;
  onFinishFailed?: (errors: Record<string, any>) => void;
}

const Form = (props: FormProps) => {
  const [values, setValues] = useState(props.initialValues || {});
  const validatorsMap = useRef(
    new Map<string, (values: any) => Promise<string>>()
  );

  const onValueChange = (key: string, value: any) => {
    setValues((prevValues) => ({ ...prevValues, [key]: value }));
  };

  const handleValidateRegister = (
    name: string,
    cb: (values: any) => Promise<string>
  ) => {
    validatorsMap.current.set(name, cb);
  };

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();

    const validators = [];

    for (const [, validator] of validatorsMap.current) {
      if (typeof validator === "function") {
        validators.push(validator);
      }
    }

    Promise.all(validators.map((validator) => validator(values))).then(
      (res) => {
        const errorList = res.filter((item) => item !== "");
        if (errorList.length) {
          props.onFinishFailed?.(errorList);
        } else {
          props.onFinish?.(values);
        }
      }
    );
  };

  return (
    <FormContext.Provider
      value={{
        values,
        setValues,
        onValueChange,
        validateRegister: handleValidateRegister,
      }}
    >
      <form onSubmit={handleSubmit}>{props.children}</form>
    </FormContext.Provider>
  );
};

export default Form;
